package engine

import (
	"container/list"
	log "github.com/cihub/seelog"
	"github.com/shopspring/decimal"
	"matching/enum"
	"matching/jobline"
	"matching/model"
)

type orderbook struct {
	buyLimitQueue orderQueue  //限价买单队列
	sellLimitQueue orderQueue  // 限价卖单队列
	buyMarketQueue orderQueue  // 市价买单队列
	sellMarketQueue orderQueue // 市价卖单队列
	symbol string				// 交易对 BTC/USDT
	coinScale int32				//交易币小数点位数
	baseCoinScale int32			//结算币小数点位数
	Queue chan model.TaskObj    //落库任务
}


// 实现交易账本初始化
func (book *orderbook) Init(symbol string,coinScale int32,baseCoinScale int32)  {
	book.buyLimitQueue.Init(enum.ASC)
	book.sellLimitQueue.Init(enum.DESC)
	book.buyMarketQueue.Init(enum.ASC)
	book.sellMarketQueue.Init(enum.ASC)
	book.coinScale=coinScale
	book.baseCoinScale=baseCoinScale
	book.symbol=symbol
}

func (book *orderbook) OrderFoundCompleted(order *model.Order,tradePrice decimal.Decimal) bool {
	var focAmount decimal.Decimal
	if order.IsMarket()&&order.Side==enum.SideBuy {
		//市价单
		focAmount = (order.Amount.Sub(order.Turnover)).DivRound(tradePrice, book.coinScale)
	} else {
		focAmount = order.Amount.Sub(order.TradedAmount)
	}
	if focAmount.Cmp(decimal.Zero)<=0 {
		return true
	}else {
		return false
	}
}



// 加入订单队列
func (book *orderbook) addOrderBook(order *model.Order)  {
	if order.Side==enum.SideBuy {
		if order.IsMarket() {
			addQueue(&book.buyMarketQueue,order)
		}else {
			addQueue(&book.buyLimitQueue,order)
		}
	}else {
		if order.IsMarket() {
			addQueue(&book.sellMarketQueue,order)
		}else {
			addQueue(&book.sellLimitQueue,order)
		}
	}
	/*log.Infof("new order add to book..........")
	log.Infof("------symbol=%s------buyLimitQueue size = %d--------------------",order.Symbol,book.buyLimitQueue.parentList.Len())
	log.Infof("------symbol=%s------sellLimitQueue size = %d--------------------",order.Symbol,book.sellLimitQueue.parentList.Len())
	log.Infof("------symbol=%s------buyMarketQueue size = %d--------------------",order.Symbol,book.buyMarketQueue.parentList.Len())
	log.Infof("------symbol=%s------sellMarketQueue size = %d--------------------",order.Symbol,book.sellMarketQueue.parentList.Len())
*/
	book.OrderChangeToDb(order)
}


func (book *orderbook) PrintBookStatus()  {
	log.Infof("------限价买单队列大小  = %d--------------------",book.buyLimitQueue.parentList.Len())
	log.Infof("------限价卖单队列大小  = %d--------------------",book.sellLimitQueue.parentList.Len())
	log.Infof("------buyMarketQueue size = %d--------------------",book.buyMarketQueue.parentList.Len())
	log.Infof("------sellMarketQueue size = %d--------------------",book.sellMarketQueue.parentList.Len())
}


func (book *orderbook) OrderChangeToDb(order *model.Order)  {
	if order.IsCompleted() {
		order.Status=enum.COMPLETED
	}
	//cache.SaveOrderObject(order)
}

func (book *orderbook)SaveTradeChangesBatch(order1 *model.Order,order2 *model.Order,price decimal.Decimal)  {
	orderBatch:=model.OrderBatch{
		Order1: order1,
		Order2: order2,
		Price: price,
	}
	jobline.ChanOrderBatchMap[orderBatch.Order1.Symbol]<-orderBatch
	//cache.SaveTradeChangesBatch(order1,order2,price)
}



// 撤单
func (book *orderbook) cancelOrderBook(order *model.Order) bool  {
	orderSort:=model.OrderSort{Symbol: order.Symbol, Action: enum.ActionCreate, OrderId: order.OrderId}
	flag:=book.removeOrder(order)

	jobline.ChanDeleteOrderMap[order.Symbol]<-orderSort
	if flag {
		order.Status=enum.CANCELED
		jobline.ChanSaveOrderMap[order.Symbol]<-*order
	}
	return flag
}

// 买单队列，价格高的排前面，时间小的排前面
func addQueue(queue *orderQueue,order *model.Order)  {
	queue.PutToQueue(order)
}


// 移除指定订单
func (book *orderbook)  removeOrder(order *model.Order)bool  {

/*	start := time.Now()
	defer func() {
		cost := time.Since(start)
		log.Infof("移除订单的花费=%d", cost)
	}()*/

	flag :=false
	var list *list.List
	if order.Side==enum.SideBuy {
		if order.IsMarket() {
			list=book.buyMarketQueue.parentList
		}else {
			list=book.buyLimitQueue.parentList
		}
	}else {
		if order.IsMarket() {
			list=book.sellMarketQueue.parentList
		}else {
			list=book.sellLimitQueue.parentList
		}
	}
	if list.Len()==0 {
		return true
	}
	//遍历list，删除元素
	for e := list.Front(); e != nil; {
		if e.Value.(*model.Order).OrderId == order.OrderId {
			list.Remove(e)
			flag=true
			break
		} else {
			e = e.Next()
		}
	}
	return flag
}




// 根据方向获取限价订单队列
func (book *orderbook) getLimitHeaderBySide(side enum.OrderSide) *model.Order {
	if side==enum.SideBuy {
		return book.getLimitHeadSellOrder()
	}else {
		return book.getLimitHeadBuyOrder()
	}
}

// 根据方向获取市价订单队列
func (book *orderbook) getMarketHeaderBySide(side enum.OrderSide) *model.Order {
	if side==enum.SideBuy {
		return book.getMarketHeadSellOrder()
	}else {
		return book.getMarketHeadBuyOrder()
	}
}


// 获取限价卖队列头部订单
func (book *orderbook) getLimitHeadSellOrder() *model.Order {
	ele:=book.sellLimitQueue.parentList.Front()
	if ele==nil {
		return nil
	}else {
		return ele.Value.(*model.Order)
	}

}
// 获取限价买队列头部订单
func (book *orderbook) getLimitHeadBuyOrder() *model.Order {
	ele:=book.buyLimitQueue.parentList.Front()
	if ele==nil {
		return nil
	}else {
		return ele.Value.(*model.Order)
	}
}

// 获取市价卖队列头部订单
func (book *orderbook) getMarketHeadSellOrder() *model.Order {
	ele:=book.sellMarketQueue.parentList.Front()
	if ele==nil {
		return nil
	}else {
		return ele.Value.(*model.Order)
	}

}
// 获取市价买队列头部订单
func (book *orderbook) getMarketHeadBuyOrder() *model.Order {
	ele:=book.buyMarketQueue.parentList.Front()
	if ele==nil {
		return nil
	}else {
		return ele.Value.(*model.Order)
	}
}




func (q *orderQueue) getDepthPrice(depth int) (string, int) {
	if q.parentList.Len() == 0 {
		return "", 0
	}
	p := q.parentList.Front()
	i := 1
	for ; i < depth; i++ {
		t := p.Next()
		if t != nil {
			p = t
		} else {
			break
		}
	}
	o := p.Value.(*list.List).Front().Value.(*model.Order)
	return o.Price.String(), i
}